package edu.uaskl.jqf.model.gates;

import edu.uaskl.jqf.model.gates.util.BaseGate;
import edu.uaskl.jqf.model.matrix.MatrixComplex;
import static edu.uaskl.jqf.tools.MathTools.ONE_OVER_SQRT_2;

public class Hadamard extends BaseGate {
    public static final MatrixComplex size2 = new MatrixComplex(new double[][] { { ONE_OVER_SQRT_2, ONE_OVER_SQRT_2 }, { ONE_OVER_SQRT_2, -ONE_OVER_SQRT_2 } });
    public static final MatrixComplex size4 = size2.tensor(size2);

    // /**
    // * Calculates the Hadamard matrix for the given size.
    // * @param size Must be size with size = n^2, n integer >
    // * @return Hadamard matrix of size size x size
    // */
    // private static Hadamard calculateAndGetForSize(final int size) {
    // if (size == 2)
    // return h2;
    // final Hadamard hadamardFromMap = mapSizeToHadamard.get(size);
    // if (hadamardFromMap != null)
    // return hadamardFromMap;
    // return h2.tensor(calculateAndGetForSize(size >> 2));
    // }
    //
    // private static Map<Integer, Hadamard> mapSizeToHadamard = new HashMap<>();

    /** works for all integer > 0 */
    private static boolean isPowerOfTwo(final int number) { // TODO math util
        return (number & (number - 1)) == 0;
    }

    @Override
    public MatrixComplex getInstance() {
        return size2;
    }

    /**
     * Returns the Hadamard matrix for the given size.
     * 
     * @param size
     *            must size with size = n^2, n integer
     * @return Hadamard matrix of size size x size
     */
    @Override
    public MatrixComplex getSize(final int size) {
        if (size == 2)
            return size2;
        if (size == 4)
            return size4;
        if (!isPowerOfTwo(size))
            throw new IllegalArgumentException("Only size with size = n^2, n integer > 1 supported at the moment");
        throw new IllegalArgumentException("Size not supported at the moment");
        // TODO just tensor 2x2 them in a loop
    }
}
